import { ref } from 'vue'
// Simple event emitter implementation (mitt-like)
type EventHandler<T = any> = (event: T) => void

interface Emitter<Events extends Record<string, any>> {
  all: Map<keyof Events, EventHandler<Events[keyof Events]>[]>
  on<Key extends keyof Events>(type: Key, handler: EventHandler<Events[Key]>): void
  off<Key extends keyof Events>(type: Key, handler?: EventHandler<Events[Key]>): void
  emit<Key extends keyof Events>(type: Key, event: Events[Key]): void
}

function mitt<Events extends Record<string, any>>(): Emitter<Events> {
  const all = new Map()
  
  return {
    all,
    on(type, handler) {
      const handlers = all.get(type)
      if (handlers) {
        handlers.push(handler)
      } else {
        all.set(type, [handler])
      }
    },
    off(type, handler) {
      const handlers = all.get(type)
      if (handlers) {
        if (handler) {
          const index = handlers.indexOf(handler)
          if (index > -1) {
            handlers.splice(index, 1)
          }
        } else {
          all.set(type, [])
        }
      }
    },
    emit(type, event) {
      const handlers = all.get(type)
      if (handlers) {
        handlers.slice().forEach((handler: EventHandler) => handler(event))
      }
    }
  }
}

// Event types for type safety
export interface AppEvents {
  // History events
  'history:version-selected': { versionId: string }
  'history:file-selected': { fileId: string, filePath: string }
  'history:files-selected': { fileIds: string[] }
  'history:folder-toggled': { folderPath: string, expanded: boolean }
  
  // Search events
  'search:query-changed': { query: string, type: 'filename' | 'content' | 'advanced' }
  'search:results-updated': { results: any[], total: number }
  'search:result-selected': { result: any }
  
  // Recovery events
  'recovery:task-added': { task: any }
  'recovery:task-removed': { taskId: string }
  'recovery:batch-started': { taskCount: number }
  'recovery:batch-completed': { successful: number, failed: number }
  'recovery:progress-updated': { completed: number, total: number }
  
  // UI events
  'ui:view-changed': { view: string }
  'ui:theme-changed': { theme: 'light' | 'dark' }
  'ui:notification-added': { notification: any }
  'ui:dialog-opened': { dialog: any }
  'ui:dialog-closed': { dialogId: string }
  
  // File operations
  'file:content-loaded': { versionId: string, fileId: string, content: string }
  'file:diff-requested': { leftFile: any, rightFile: any }
  'file:preview-requested': { versionId: string, fileId: string }
  
  // Diff operations
  'diff:comparison-completed': { leftFile: any, rightFile: any }
  'diff:files-selected': { leftFile: any, rightFile: any }
  
  // Error events
  'error:occurred': { error: Error, context: string }
  'error:cleared': { context?: string }
  
  // Cache events
  'cache:invalidated': { type: 'history' | 'search' | 'all' }
  'cache:updated': { type: string, key: string, data: any }
}

// Create event emitter instance
const eventBus: Emitter<AppEvents> = mitt<AppEvents>()

// Event bus composable
export function useEventBus() {
  return {
    emit: eventBus.emit,
    on: eventBus.on,
    off: eventBus.off,
    all: eventBus.all
  }
}

// Event history for debugging
const eventHistory = ref<Array<{
  event: keyof AppEvents
  data: any
  timestamp: Date
}>>([])

// Enhanced event bus with history tracking
export function useEventBusWithHistory() {
  const bus = useEventBus()
  
  const emit = <T extends keyof AppEvents>(event: T, data: AppEvents[T]) => {
    // Add to history
    eventHistory.value.push({
      event,
      data,
      timestamp: new Date()
    })
    
    // Keep only last 1000 events
    if (eventHistory.value.length > 1000) {
      eventHistory.value = eventHistory.value.slice(-1000)
    }
    
    // Emit the event
    bus.emit(event, data)
  }
  
  const getEventHistory = () => eventHistory.value
  
  const clearEventHistory = () => {
    eventHistory.value = []
  }
  
  const getEventsByType = <T extends keyof AppEvents>(eventType: T) => {
    return eventHistory.value.filter(e => e.event === eventType)
  }
  
  return {
    emit,
    on: bus.on,
    off: bus.off,
    all: bus.all,
    getEventHistory,
    clearEventHistory,
    getEventsByType
  }
}

// Event middleware for cross-store communication
export class EventMiddleware {
  private static instance: EventMiddleware
  private bus = useEventBus()
  
  static getInstance(): EventMiddleware {
    if (!EventMiddleware.instance) {
      EventMiddleware.instance = new EventMiddleware()
    }
    return EventMiddleware.instance
  }
  
  private constructor() {
    this.setupEventHandlers()
  }
  
  private setupEventHandlers() {
    // History -> Search integration
    this.bus.on('history:version-selected', ({ versionId: _versionId }) => {
      // Update search context when version changes
      this.bus.emit('search:query-changed', { 
        query: '', 
        type: 'filename' 
      })
    })
    
    // Search -> Recovery integration
    this.bus.on('search:result-selected', ({ result }) => {
      // Auto-add search result to recovery queue if requested
      this.bus.emit('recovery:task-added', { 
        task: this.createRecoveryTaskFromSearchResult(result) 
      })
    })
    
    // Recovery -> UI integration
    this.bus.on('recovery:batch-started', ({ taskCount }) => {
      this.bus.emit('ui:notification-added', {
        notification: {
          type: 'info',
          title: '开始批量恢复',
          message: `正在恢复 ${taskCount} 个文件...`
        }
      })
    })
    
    this.bus.on('recovery:batch-completed', ({ successful, failed }) => {
      this.bus.emit('ui:notification-added', {
        notification: {
          type: successful > 0 && failed === 0 ? 'success' : 'warning',
          title: '批量恢复完成',
          message: `成功: ${successful}, 失败: ${failed}`
        }
      })
    })
    
    // Error handling
    this.bus.on('error:occurred', ({ error, context }) => {
      this.bus.emit('ui:notification-added', {
        notification: {
          type: 'error',
          title: '操作失败',
          message: `${context}: ${error.message}`
        }
      })
    })
  }
  
  private createRecoveryTaskFromSearchResult(result: any) {
    return {
      versionId: result.versionId,
      fileId: result.fileId,
      originalPath: result.originalPath,
      targetPath: result.originalPath // Default to same path
    }
  }
}

// Initialize event middleware
EventMiddleware.getInstance()

// Utility functions for common event patterns
export function emitError(error: Error, context: string) {
  const bus = useEventBus()
  bus.emit('error:occurred', { error, context })
}

export function emitSuccess(message: string, title = '操作成功') {
  const bus = useEventBus()
  bus.emit('ui:notification-added', {
    notification: {
      type: 'success',
      title,
      message
    }
  })
}

export function emitProgress(completed: number, total: number) {
  const bus = useEventBus()
  bus.emit('recovery:progress-updated', { completed, total })
}

// Event subscription helpers
export function onHistoryEvent<T extends keyof AppEvents>(
  event: T,
  handler: (data: AppEvents[T]) => void
) {
  const bus = useEventBus()
  bus.on(event, handler)
  
  // Return unsubscribe function
  return () => bus.off(event, handler)
}

// Batch event operations
export function emitBatch(events: Array<{ event: keyof AppEvents, data: any }>) {
  const bus = useEventBus()
  events.forEach(({ event, data }) => {
    bus.emit(event as any, data)
  })
}

// Event debouncing
export function createDebouncedEmitter<T extends keyof AppEvents>(
  event: T,
  delay: number = 300
) {
  let timeoutId: NodeJS.Timeout | null = null
  const bus = useEventBus()
  
  return (data: AppEvents[T]) => {
    if (timeoutId) {
      clearTimeout(timeoutId)
    }
    
    timeoutId = setTimeout(() => {
      bus.emit(event, data)
      timeoutId = null
    }, delay)
  }
}

// Event throttling
export function createThrottledEmitter<T extends keyof AppEvents>(
  event: T,
  delay: number = 100
) {
  let lastEmit = 0
  const bus = useEventBus()
  
  return (data: AppEvents[T]) => {
    const now = Date.now()
    if (now - lastEmit >= delay) {
      bus.emit(event, data)
      lastEmit = now
    }
  }
}